
import { _decorator, Animation, EventTouch, Label, Mask, Node, Rect, Size, tween, Tween, UITransform, v2, v3, Vec3 } from 'cc';
import { BaseUI } from '../../framework/base/BaseUI';
import { BaseEventName } from '../../framework/config/Appcfg';
import { EventMgr } from '../../framework/manager/EventMgr';



const { ccclass, property } = _decorator;


export enum DirPos {
    /**上方右边 */
    TopRight,
    /**上方左边 */
    TopLeft,
    BottomLeft,
    BottomRight,
}
export class GuildCfg {
    /**点击 0：点击 1：滑动 */
    clickType: number = 0
    /**目标节点 */
    distNode: Node = null;
    /**指引的文字 */
    tipstring: string = null;
    /**tips方位 */
    dir: DirPos = DirPos.BottomLeft;
    /**是否是弱引导 */
    isWeek: boolean = false;
    /**高亮的图形 0:圆形 1：方形 */
    lightType: number = 1;
    /**是否需要显示手指 */
    showHand: boolean = true;
    /**延时出现 */
    delay: number = 0.02
    /**滑动 开始位置 */
    startNode: Node = null;
    /**滑动 结束位置 */
    endNode: Node = null;
    /**滑动时间 */
    moveTime: number = 1
    moveNodeshow: Node = null;
    /**隐藏mask */
    hideMask: boolean = false;
    /**需要加多少的框 */
    addSize: Size = new Size(10, 20)

    /**手指坐标偏移 */
    handOffset: Vec3 = new Vec3(0, 0, 0)

    isNext: boolean = false;
    /**关闭UI回调 */
    closeUICallBack: Function = null;

    /**点击后是否走自己的回调 */
    callBack: Function = null;
    needShowTarget: boolean = false
    /**滑动 移动完成 改变这个值会自动关闭UIGuide */
    finishMoveEnd: boolean = false;

    constructor() {
        EventMgr.getInstance().emit(BaseEventName.blocktouch, false)
    }

}


@ccclass('UIGuide')
export class UIGuide extends BaseUI {
    @property(Mask)
    mask: Mask = null;
    @property(Node)
    hand: Node = null;
    @property(Node)
    tipBg: Node = null;
    @property(Boolean)
    isMove: Boolean = true;
    @property(Label)
    tipText: Label = null;
    private distNode: Node = null;
    private dirPos: DirPos = DirPos.TopRight;
    private cfg: GuildCfg;

    maskScaleTime: number = 0.3;
    init(cfg: GuildCfg) {
        if (!cfg.delay || cfg.delay < 0.1) {
            cfg.delay = 0.02
        }
        this.cfg = cfg;

    }

    private clickTouch(cfg: GuildCfg) {
        this.hand.active = false;
        this.tipBg.active = false;
        this.cfg = cfg;
        if (cfg.dir) {
            this.dirPos = cfg.dir;
        }
        this.distNode = cfg.distNode;
        let size: Size;
        if(!this.distNode){
            return new Error("请设置目标节点")
        }
        let p = this.distNode.getWorldPosition()
        if (cfg.distNode) {
            let poss = this.mask.node.parent.getComponent(UITransform).convertToNodeSpaceAR(p)
            this.mask.node.setPosition(poss);
            this.mask.node.getComponent(UITransform).setContentSize(900, 900)
            size = cfg.distNode.getComponent(UITransform).contentSize;
        } else {
            size = new Size(0, 0)
        }
        this.mask.node.active = true;
        this.scheduleOnce(() => {
            if (cfg.lightType == 0) {
                this.mask.type = Mask.Type.GRAPHICS_ELLIPSE;
            } else {
                this.mask.type = Mask.Type.GRAPHICS_RECT;
            }
        }, 0.01)

        if (cfg.hideMask) {
            this.mask.node.active = false;
        } else {
            this.mask.node.active = true;
        }
        if (cfg.isWeek) {
            this.scheduleOnce(() => {
                EventMgr.getInstance().emit(BaseEventName.blocktouch, true)
            }, 0.1)
            this.showHand();
            this.showTip(cfg.tipstring)
        }
        if (this.mask.node.active) {
            tween(this.mask.node.getComponent(UITransform))
                .to(this.maskScaleTime, { width: size.width + this.cfg.addSize.width, height: size.height + this.cfg.addSize.height })
                .call(() => {
                    this.showHand();
                    this.showTip(cfg.tipstring)
                }).delay(0.1).call(() => {
                    EventMgr.getInstance().emit(BaseEventName.blocktouch, true)
                })
                .start();
        }
    }
    private moveTween: Tween<Node>
    moveTouch(cfg: GuildCfg) {
        if (cfg.startNode && cfg.endNode) {
            this.schedule(() => {
                if (this.cfg.finishMoveEnd) {
                    this.unscheduleAllCallbacks()
                    this.closeUI()
                }
            })

            if (cfg.hideMask) {
                this.mask.node.active = false;
            } else {
                this.mask.node.active = true;
            }
            this.mask.node.active = true;
            let startWPos = cfg.startNode.getComponent(UITransform).convertToWorldSpaceAR(Vec3.ZERO)
            let endWPos = cfg.endNode.getComponent(UITransform).convertToWorldSpaceAR(Vec3.ZERO)
            let spos = this.hand.parent.getComponent(UITransform).convertToNodeSpaceAR(startWPos)
            let epos = this.hand.parent.getComponent(UITransform).convertToNodeSpaceAR(endWPos)
            this.scheduleOnce(() => {
                this.hand.getComponent(Animation).stop();
            }, 0.2)
            this.hand.setPosition(spos)
            this.hand.active = true;
            this.moveTween = tween(this.hand)
                .to(cfg.moveTime, { position: new Vec3(epos.x, epos.y) })
                .delay(0.5)
                .call(() => {
                    this.hand.setPosition(spos)
                }).union().repeatForever();
            this.moveTween.start();
            if (!cfg.hideMask) {
                let width = Math.abs(epos.x - spos.x)
                let height = Math.abs(epos.y - spos.y)
                height = Math.max(cfg.startNode.getComponent(UITransform).height, cfg.endNode.getComponent(UITransform).height, height)
                width = Math.max(cfg.startNode.getComponent(UITransform).width, cfg.endNode.getComponent(UITransform).width, width)
                let x: number = spos.x;
                let y: number = spos.y;
                if (spos.x > epos.x) {
                    if (spos.x > 0 && epos.x > 0) {
                        x = (spos.x - epos.x) * 0.5
                    } else if (spos.x > 0 && epos.x < 0) {
                        x = (spos.x + epos.x) * 0.5
                    } else if (spos.x < 0 && epos.x < 0) {
                        x = (spos.x + epos.x) * 0.5
                    }
                } else if (spos.x < epos.x) {
                    if (spos.x > 0 && epos.x > 0) {
                        x = (epos.x - spos.x) * 0.5
                    } else if (spos.x > 0 && epos.x < 0) {
                        x = (spos.x + epos.x) * 0.5
                    } else if (spos.x < 0 && epos.x < 0) {
                        x = (spos.x + epos.x) * 0.5
                    }
                }
                if (spos.y > epos.y) {
                    if (spos.y > 0 && epos.y > 0) {
                        y = spos.y - epos.y
                    } else if (spos.y > 0 && epos.y < 0) {
                        y = spos.y + epos.y
                    } else if (spos.y < 0 && epos.y < 0) {
                        y = spos.y + epos.y
                    } else if (spos.y < 0 && epos.y > 0) {
                        y = spos.y + epos.y
                    }
                } else {
                    if (spos.y > 0 && epos.y > 0) {
                        y = epos.y - spos.y
                    } else if (spos.y > 0 && epos.y < 0) {
                        y = spos.y + epos.y
                    } else if (spos.y < 0 && epos.y < 0) {
                        y = spos.y + epos.y
                    } else if (spos.y < 0 && epos.y > 0) {
                        y = spos.y + epos.y
                    }
                }
                let pos = v2(x, y * 0.5)
                this.mask.node.setPosition(pos.x, pos.y, 0)
                let size = new Size(width + cfg.startNode.getComponent(UITransform).width, height + cfg.startNode.getComponent(UITransform).height)
                tween(this.mask.node.getComponent(UITransform))
                    .to(this.maskScaleTime, { width: size.width + this.cfg.addSize.width, height: size.height + this.cfg.addSize.height })
                    .call(() => {
                        this.showHand();
                        this.showTip(cfg.tipstring)
                    })
                    .start();
            } else {
                this.showHand();
                this.showTip(cfg.tipstring)
            }
        } else {
            this.closeUI();
        }
    }
    start() {
        this.scheduleOnce(() => {
            if (this.cfg.clickType == 0) {
                this.clickTouch(this.cfg)
            } else {
                this.moveTouch(this.cfg)
            }
        }, this.cfg.delay)
        //监听事件
        this.node.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
            if (this.distNode || this.cfg.startNode) {
                //目标区域存在，击中放行
                let rect: Rect
                if (this.cfg.clickType != 0) {
                    rect = this.cfg.startNode.getComponent(UITransform).getBoundingBoxToWorld();
                } else {
                    rect = this.distNode.getComponent(UITransform).getBoundingBoxToWorld();
                }
                if (rect.contains(event.getUILocation())) {
                    if (this.cfg.callBack) {
                        this.cfg.callBack(true);
                    } else {
                        this.node.off(Node.EventType.TOUCH_START)
                        event.preventSwallow = true;

                    }
                    if (this.cfg.clickType == 0) {
                        this.closeUI();
                    }
                } else {
                    //放行
                    if (this.cfg.isWeek) {
                        if (this.cfg.callBack) {
                            this.cfg.callBack();
                        } else {
                            event.preventSwallow = true;
                        }
                        this.closeUI();
                        return;
                    }
                    if (this.cfg.needShowTarget) {
                        let size: Size;
                        let p = this.distNode.getWorldPosition()
                        if (this.cfg.distNode) {
                            let poss = this.mask.node.parent.getComponent(UITransform).convertToNodeSpaceAR(p)
                            this.mask.node.setPosition(poss);
                            this.mask.node.getComponent(UITransform).setContentSize(900, 900)
                            size = this.cfg.distNode.getComponent(UITransform).contentSize;
                        } else {
                            size = new Size(0, 0)
                        }
                        this.mask.node.active = true
                        tween(this.mask.node.getComponent(UITransform))
                            .to(this.maskScaleTime, { width: size.width + this.cfg.addSize.width, height: size.height + this.cfg.addSize.height })
                            .call(() => {
                                this.showHand();
                                this.showTip(this.cfg.tipstring)
                            })
                            .start();
                    }
                }
            } else {
                //放行
                if (this.cfg.isWeek) {
                    if (this.cfg.callBack) {
                        this.cfg.callBack();
                    } else {
                        event.preventSwallow = true;

                    }
                    this.closeUI();
                    return;
                }
            }
        }, this);
        this.mask.node.getChildByName("bg").on(Node.EventType.TOUCH_START, (event: EventTouch) => {
            //放行
            if (this.cfg.isWeek || !this.mask.node.active) {
                if (this.cfg.callBack) {
                    this.cfg.callBack();
                } else {
                    event.preventSwallow = (true);
                }
                this.closeUI();
                return;
            }
            //目标区域存在，击中放行
            if (this.distNode) {
                let rect = this.distNode.getComponent(UITransform).getBoundingBoxToWorld();
                if (rect.contains(event.getUILocation())) {
                    if (this.cfg.callBack) {
                        this.cfg.callBack(true);
                    } else {
                        event.preventSwallow = (true);
                    }
                    this.closeUI();
                }
            }
        }, this)
    }
    showHand() {
        if (this.cfg.showHand) {
            this.hand.setPosition(this.mask.node.position.clone().add(this.cfg.handOffset))
            this.hand.active = true;
        }
    }
    showTip(text: string) {
        if (text && text.length > 0) {
            this.tipBg.active = true;
            this.isMove&&this.tipBg.setPosition(this.mask.node.position.x, this.mask.node.position.y + 50)
            this.tipText.string = text;
            let orginScalex = Math.abs(this.tipBg.scale.x);
            let orginScaleY = Math.abs(this.tipBg.scale.y);
            let textScaleX = Math.abs(this.tipText.node.scale.x);
            let textScaleY = Math.abs(this.tipText.node.scale.y);
            if (this.dirPos == DirPos.TopLeft) {
                let scale = v3(orginScalex, -this.tipBg.getScale().y)
                this.tipBg.setScale(scale)
                scale = v3(textScaleX, - this.tipText.node.getScale().y)
                this.tipText.node.setScale(scale)
            } else if (this.dirPos == DirPos.TopRight) {
                let scale = v3(-orginScalex, -this.tipBg.getScale().y)
                this.tipBg.setScale(scale)
                scale = v3(-textScaleX, -this.tipText.node.getScale().y)
                this.tipText.node.setScale(scale)
            } else if (this.dirPos == DirPos.BottomLeft) {
                let scale = v3(orginScalex, orginScaleY)
                this.tipBg.setScale(scale)
                scale = v3(textScaleX, textScaleY)
                this.tipText.node.setScale(scale)
                this.isMove&& this.tipBg.setPosition(this.mask.node.position.x, this.mask.node.position.y - 50)
            } else if (this.dirPos == DirPos.BottomRight) {
                let scale = v3(-this.tipBg.getScale().x, orginScaleY)
                this.tipBg.setScale(scale)
                scale = v3(-textScaleX, textScaleY)
                this.tipText.node.setScale(scale)
                this.isMove&& this.tipBg.setPosition(this.mask.node.position.x, this.mask.node.position.y - 50)
            }

        } else {
            this.tipBg.active = false;
        }
    }

    closeUI() {
       super.closeUI();
        console.log("关闭引导");
        this.cfg.closeUICallBack && this.cfg.closeUICallBack.call(this)
    }

}
